﻿#include "stdafx.h"
#include "RecordTableModel.h"
#include <QLineEdit>
#include <QPainter>
#include <QDateEdit>
#include <QSpinBox>
#include <QMessageBox>

//======================================================================================================================

QRecordTableModel::QRecordTableModel( QObject * parent ) : QAbstractItemModel( parent )
{

}

QRecordTableModel::~QRecordTableModel( )
{

}

bool QRecordTableModel::select( const QString & SQL )
{
	return dsRecords.select(SQL);
}

bool QRecordTableModel::select(const QString & SQL, QString & Error)
{
	return dsRecords.select(SQL, Error);
}

void QRecordTableModel::refresh( )
{
	beginResetModel( );
	endResetModel( );
}

void QRecordTableModel::addCol(const QString & name, COLUMN_TYPE type, COLUMN_FLAGS flags, const QString & alias)
{
	dsRecords.addCol(name, type, flags, alias);
}

void QRecordTableModel::addRow(const QList<QVariant> & value)
{
	dsRecords.addRow(value);
}

void QRecordTableModel::removeRow(int row)
{
	dsRecords.removeRow(row);
}

void QRecordTableModel::setCol( QString name, COLUMN_FLAGS flags, const QString & alias )
{
	dsRecords.setCol( name, flags, alias );
}

void QRecordTableModel::setCol( int col, COLUMN_FLAGS flags, const QString & alias )
{
	dsRecords.setCol( col, flags, alias );
}

void QRecordTableModel::setAt(int row, int col, QVariant value)
{
	dsRecords.setAt(row, col, value);
}

QRecordTable & QRecordTableModel::records( )const
{
	return dsRecords;
}

QModelIndex QRecordTableModel::getModelByIndex( int rowIndex ) const
{
	return createIndex( rowIndex , 0 , rowIndex ); 
}

QModelIndex QRecordTableModel::getFindIndex( int col, const QString & text )
{
	//模糊匹配
    Q_UNUSED(col)
    Q_UNUSED(text)
	return QModelIndex( );
}

QVariant QRecordTableModel::getItemData(int row, int col)
{
	return dsRecords.data(row, col);
}

//======================================================================================================================
QVariant QRecordTableModel::headerData(int section, Qt::Orientation orientation, int role ) const
{
	if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
	{
		if( dsRecords.colCount( ) > section )
		{
			short col = dsRecords.showRecords( ).at( section );
			return dsRecords.getColAlias(col);
		}
	}
	return QVariant( );
}

QModelIndex QRecordTableModel::index( int row , int column , const QModelIndex & parent ) const
{
    if( !hasIndex( row, column, parent ) )
        return QModelIndex( );

	return createIndex( row, column, row );
}

QVariant QRecordTableModel::data( const QModelIndex & index , int role ) const
{
	if( role != Qt::DisplayRole || !index.isValid( ) ) return QVariant( );
	
	return display( index.column( ) , dsRecords.showData( index.row( ), index.column( ) ) ) ;

}

bool QRecordTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	return QAbstractItemModel::setData(index, value, role);
}

QModelIndex QRecordTableModel::parent( const QModelIndex & child ) const
{
    Q_UNUSED(child)
	return QModelIndex( );
}

int QRecordTableModel::columnCount( const QModelIndex & parent ) const
{
    Q_UNUSED(parent)
	return dsRecords.showColCount( );
}

int QRecordTableModel::rowCount( const QModelIndex & parent ) const
{
    if( parent.column( ) > 0 )
        return 0;

	if( parent == QModelIndex( ) )
		return dsRecords.rowCount( );

	return 0;
}

Qt::ItemFlags QRecordTableModel::flags( const QModelIndex &index ) const
{
    if(!index.isValid( )) 
		return 0;

	if(index.column( ) >= dsRecords.showRecords( ).count( )) 
		return QAbstractItemModel::flags( index );

	if(dsRecords.showFlags(index.column()) & CF_EDIT)
		return Qt::ItemIsEditable | QAbstractItemModel::flags( index );

	return QAbstractItemModel::flags( index );
}

QVariant QRecordTableModel::display( int col , const QVariant & value ) const
{
    Q_UNUSED(col)

	//翻译使用。
	return value;
}

//delegate新加
//======================================================================================================================
bool QRecordTableModel::modifyRow(int row, int col, const QVariant & value)
{
	return dsRecords.setAt(row, col, value);
}

bool QRecordTableModel::modifyRow(const QModelIndex & index, const QVariant & value)
{
	return dsRecords.modifyShow(index.row(), index.column(), value);
}

bool QRecordTableModel::deleteRow(const QModelIndex & index)
{
	//删除时不真正删除， 只是标记下来。
	CHK_EXP_RET(!index.isValid(), false);
	bool bRes = dsRecords.deleteRow(index.internalId());
	CHK_EXP_RUN(bRes, emit dataChanged(createIndex(index.row(), 0),
		createIndex(index.row(), columnCount())));
	return bRes;
}

QModelIndex QRecordTableModel::insertRow(QVariantList & value, bool bSeq)
{
	//若为联合主键， 则不生成ID
	//若主键为空，新增数据需要生成新的ID。
	int RowIndex = dsRecords.insertRow(value, bSeq);
	CHK_EXP_RET(RowIndex < 0, QModelIndex());
	refresh();
	return createIndex(RowIndex, 0, RowIndex);
}

int QRecordTableModel::saveData(QString & Error, bool Refreshed)
{
	//int Caller = dsRecords.saveData(Error, Refreshed);
	//CHK_EXP_RUN(Caller == 0, refresh());
	//return Caller;
	return 0;
}

int QRecordTableModel::cancelSaveData()
{
	//需要从数据库中重新加载数据源。
	int Caller = recordsChanged();
	//CHK_EXP_RUN(Caller == 0, Caller = dsRecords.refreshData());
	//CHK_EXP_RUN(Caller == 0, refresh());
	return Caller;
}

int QRecordTableModel::recordsChanged()
{
	//数据源改变提醒， 不会从数据库重新刷新数据
	if (dsRecords.editRecords().count() > 0)
	{
		switch (QMessageBox::information(NULL, tr("Operation confirmation"),
			tr("Data has modified, Do you want to save data?"),
			tr("Yes"), tr("No"), 0, 1))
		{
		case 0:
		{
				  QString Error;
				  // return dsRecords.saveData(Error);
		}
		case 1:
		{
				  dsRecords.clearEditFlags();
				  break;
		}
		}
	}

	return true;

}

//----------------------------------------------------------------------------------------------------

bool QRecordTableModel::deleteRow(int index) const
{
	if (dsRecords.editRecords().contains(index))
	{
		if (dsRecords.editRecords().value(index) == RET_DELETE)
			return true;
	}
	return false;
}


//=====================================================================================================

QEditTableDelegate::QEditTableDelegate(QObject * parent) : QStyledItemDelegate(parent)
{

}

QEditTableDelegate::~QEditTableDelegate()
{

}

void QEditTableDelegate::InitComboBox(const QModelIndex &index, QComboBox * editor) const
{
	//初始化COMBOBOX并设置位置。重载实现。
	editor->addItem(tr("father"));
	editor->addItem(tr("father1"));
	editor->addItem(tr("father2"));
	editor->addItem(tr("father3"));
}

QWidget * QEditTableDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
	const QRecordTableModel * pEditModel = qobject_cast<const QRecordTableModel *>(index.model());
	COLUMN_FLAGS Flag = pEditModel->records().showFlags(index.column());
	CHK_EXP_RET(Flag & CF_COMBOBOX, new QComboBox(parent));
	CHK_EXP_RET(Flag & CF_DATE, new QDateEdit(parent));
	CHK_EXP_RET(Flag & CF_SPINBOX, new QSpinBox(parent));
	CHK_EXP_RET(Flag & CF_DOUBLESPINBOX, new QDoubleSpinBox(parent));
	return new QLineEdit(parent);
}

void QEditTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
	const QRecordTableModel * pEditModel = qobject_cast<const QRecordTableModel *>(index.model());
	COLUMN_FLAGS Flag = pEditModel->records().showFlags(index.column());
	if (Flag & CF_COMBOBOX)
	{
		QComboBox * box = qobject_cast<QComboBox *>(editor);
		InitComboBox(index, box);
		int pos = box->findText(index.data().toString());
		CHK_EXP_RUN(pos == -1, pos = box->findData(index.data().toString()))
			box->setCurrentIndex(pos);
		return;
	}

	if (Flag & CF_DATE)
	{
		QDate nDate = index.data().toDate();
		nDate = QDate::currentDate();
		QDateEdit* pDateEdit = qobject_cast<QDateEdit*>(editor);
		pDateEdit->setDate(nDate);
		return;
	}

	if (Flag & CF_SPINBOX)
	{
		QSpinBox * pEditBox = qobject_cast<QSpinBox *>(editor);
		int Value = index.data().toInt();
		pEditBox->setValue(Value);
		return;
	}

	if (Flag & CF_DOUBLESPINBOX)
	{
		QDoubleSpinBox * pEditBox = qobject_cast<QDoubleSpinBox *>(editor);
		double Value = index.data().toDouble();
		pEditBox->setValue(Value);
		return;
	}

	QLineEdit * edit = qobject_cast<QLineEdit *>(editor);
	edit->setText(index.data().toString());
}

void QEditTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
	QRecordTableModel * pEditModel = qobject_cast<QRecordTableModel *>(model);
	COLUMN_FLAGS Flag = pEditModel->records().showFlags(index.column());
	if (Flag & CF_COMBOBOX)
	{
		QVariant Source;
		QComboBox * box = qobject_cast<QComboBox *>(editor);
		short Col = pEditModel->records().showRecords().at(index.column());
		Source = pEditModel->records().data(index.row(), index.column());
		CHK_EXP_RUN(Source != box->currentText(), pEditModel->modifyRow(index, box->currentText()));
		return;
	}

	if (Flag & CF_DATE)
	{
		QDateEdit* pDateEditor = qobject_cast<QDateEdit *>(editor);
		QDate nDateEdit = pDateEditor->date();
		QDate nData = index.data().toDate();
		CHK_EXP_RUN(nDateEdit != nData, pEditModel->modifyRow(index, nDateEdit));
		return;
	}

	if (Flag & CF_SPINBOX)
	{
		QSpinBox * pEditBox = qobject_cast<QSpinBox *>(editor);
		int Value = pEditBox->value();
		int OldValue = index.data().toInt();
		CHK_EXP_RUN(Value != OldValue, pEditModel->modifyRow(index, Value));
		return;
	}

	if (Flag & CF_DOUBLESPINBOX)
	{
		QDoubleSpinBox * pEditBox = qobject_cast<QDoubleSpinBox *>(editor);
		double Value = pEditBox->value();
		double OldValue = index.data().toDouble();
		CHK_EXP_RUN(Value != OldValue, pEditModel->modifyRow(index, Value));
		return;
	}

	QLineEdit * edit = qobject_cast<QLineEdit *>(editor);
	if (index.data().toString() != edit->text())
	{
		QRecordTableModel * pEditModel = qobject_cast<QRecordTableModel *>(model);
		pEditModel->modifyRow(index, edit->text());
	}
}

void QEditTableDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	editor->setGeometry(option.rect);
}

void QEditTableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	QStyledItemDelegate::paint(painter, option, index);

	const QRecordTableModel * pEditModel = qobject_cast<const QRecordTableModel *>(index.model());
	if (pEditModel->deleteRow(index.row()))
	{
		//已删除未保存的绘制删除线。
		painter->save();
		QRect rc = option.rect;
		painter->setPen(Qt::gray);
		painter->drawLine(rc.x(), rc.y() + rc.height() / 2, rc.x() + rc.width(), rc.y() + rc.height() / 2);
		painter->restore();
	}
}
